package com.whately.core.base.config.aspect;

import com.alibaba.fastjson.JSON;
import com.whately.core.base.annotation.WhRecorderOperate;
import com.whately.core.base.config.SpringConfigurer;
import com.whately.core.base.constant.LoginUser;
import com.whately.core.base.event.RecorderOperateBean;
import com.whately.core.base.event.RecorderOperateEvent;
import com.whately.core.base.helper.CacheHelper;
import com.whately.core.base.jwt.JwtLoginUserUtil;
import com.whately.core.base.model.ApiResponse;
import com.whately.core.base.model.RecorderInfoBO;
import com.whately.core.base.model.RecorderModel;
import com.whately.core.base.utils.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Method;

/**
 * 后台操作记录拦截器
 * 操作完成后记录日志
 */
@Aspect
@Configuration
@Slf4j
public class WhRecorderOperateAspect {

    @Value("${myconfig.whlog.contentlength:1000}")
    private int contentLength ;

    //
    @Pointcut("@annotation(com.whately.core.base.annotation.WhRecorderOperate)")
    public void pointCut() {
    }

    @Around(value = "pointCut()")
    public Object processTx(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        //String signatureName = signature.getName();
        Method method = signature.getMethod();
        WhRecorderOperate operateRecorder = method.getAnnotation(WhRecorderOperate.class);

        //执行之前

        //执行方法
        Object result =  point.proceed();

        //执行之后：记录日志
        RecorderModel recordModel = new RecorderModel();

        String operateContent=null;
        String beforeOperateContent=null;
        String descr = getStr(operateRecorder.desc(), 255);
        int typ = operateRecorder.typ();
        recordModel.setTyp(typ);
        if(result!=null){
            if (result instanceof ApiResponse) {
                ApiResponse apiResponseResult = (ApiResponse) result;

                //不记录日志标志，直接返回
                if(apiResponseResult.isRecorderIgnore()){
                    return result;
                }

                Object recorderInfo = apiResponseResult.getRecorderInfo();
                if(recorderInfo !=null){
                    if(recorderInfo instanceof RecorderInfoBO){
                        RecorderInfoBO bo = (RecorderInfoBO)recorderInfo;
                        setBo(bo,recordModel);
                        operateContent = CacheHelper.value2String(bo.getContent());
                        beforeOperateContent = CacheHelper.value2String(bo.getContentBefore());

                        descr =  getStr(descr.replace("{}",bo.getDescrReplace()), 255);

                    }else{
                        operateContent = CacheHelper.value2String(recorderInfo);
                    }

                    //移除日志信息
                    apiResponseResult.setRecorderInfo(null);
                }
            } else if (result instanceof RecorderInfoBO) {
                RecorderInfoBO bo = (RecorderInfoBO)result;
                setBo(bo,recordModel);
                operateContent = CacheHelper.value2String(bo.getContent());
                beforeOperateContent = CacheHelper.value2String(bo.getContentBefore());

                descr =  getStr(descr.replace("{}",bo.getDescrReplace()), 255);

            }else {
                operateContent = JSON.toJSONString(result);
            }
        }


        //如果jwt的user 信息存在，重新指定记录操作人id和name
        JwtLoginUserUtil u = new JwtLoginUserUtil();
        LoginUser loginUser = u.getLoginUser();
        if(loginUser!=null){
            recordModel.setOperatorId(loginUser.getUserIdNumber());
            recordModel.setOperatorName(loginUser.getUserName());
        }

        //记录操作时间
        long ts = DateUtil.nowSecond();
        recordModel.setCreateTime(ts);

        recordModel.setDescr(descr);
        recordModel.setContent(getStr(operateContent,contentLength));
        recordModel.setContentBefore(getStr(beforeOperateContent,contentLength));

        //事件处理
        RecorderOperateBean operateBean = new RecorderOperateBean(recordModel,operateRecorder.handlerType(),operateRecorder.handlerCode());
        SpringConfigurer.getApplicationContext().publishEvent(new RecorderOperateEvent(this, operateBean));

        return result;
    }

    private void setBo(RecorderInfoBO bo,RecorderModel recordModel){
        if(bo.getTyp()!=null&&bo.getTyp()>0){
            recordModel.setTyp(bo.getTyp());
        }

        recordModel.setBizId(bo.getBizId());
        recordModel.setCid(bo.getCid()==null?0L:bo.getCid());

        //操作人id和操作人name
        recordModel.setOperatorId(bo.getOperatorId());
        recordModel.setOperatorName(bo.getOperatorName());
    }
    private String getStr(String cont,int maxLength){
        if(cont==null){
            return StringUtils.EMPTY;
        }
        if(cont.length()<=maxLength){
            return cont;
        }else{
            return cont.substring(0,maxLength);
        }
    }

}
